<?php

namespace Aoe\Emulator\Controller;



use Aoe\Core\Controller;
use Aoe\Database\SqlBuilder;
use Aoe\Emulator\Ifc\Key;
use Aoe\Emulator\Ifc\Vu;
use Aoe\Emulator\Processor\Entity;
use Aoe\Emulator\Processor\Search;
use Aoe\Emulator\Schema\Model;
use Aoe\Emulator\Schema\Models;
use Aoe\Intent\Request\Request;
use Exception;

/**
 * # Aoe基础控制器类
 */
class Aoe extends Controller
{
    /**
     * 指定数据库
     */
    const string PLATFORM = 'platform';
    const string FIELDS   = 'fields';
    const string COLUMNS  = 'columns';
    const string ELEMENTS = 'elements';

    private ?Models  $schema     = null {
        get {
            if (!$this->schema) $this->schema = $this->kernel->Smart()->getModelsOf($this->module);
            return $this->schema;
        }
    }
    private ?SqlBuilder $database   = null;

    /**
     * @param string|null $model
     *
     * @return Model
     * @throws Exception
     */
    public function getModel(?string $model = null): Model
    {
        return $this->schema->get($model ?? $this->name);
    }

    public function getViewDeclarer(Request | string | null $request): array
    {
        return $request === null
            ? $this->getConfigOf(null, [])
            : $this->get_action_def($request)[Vu::SCHEMA] ?? [];
    }

    protected function get_action_def(Request | string $request): array
    {
        $action = is_string($request) ? $request : $request->section->action;
        return $this->getConfigOf(strtolower($action), []);
    }

    /**
     * @param int $id
     *
     * @return SqlBuilder
     * @throws Exception
     */
    protected function get_database(int $id = -1): SqlBuilder
    {
        if ($id < 0) {
            if (!$this->database) {
                $id = $this->module->config->get(self::PLATFORM, 0);
                $this->database = $this->kernel->Database()->use($id);
            }
            return $this->database;
        }
        return $this->kernel->Database()->use($id);
    }

    /**
     * @param null | Model | string $collection
     *
     * @return Search
     * @throws Exception
     */
    protected function create_search(null | Model | string $collection = null): Search
    {
        return new Search($this->_get_model($collection), $this->get_database());
    }

    /**
     * @param Model|string|null $collection
     *
     * @return Entity
     * @throws Exception
     */
    protected function create_entity(null | Model | string $collection = null): Entity
    {
        return new Entity($this->_get_model($collection), $this->get_database());
    }

    /**
     * @throws Exception
     */
    private function _get_model(null | string | Model $collection = null): Model
    {
        return $collection instanceof Model ? $collection : $this->getModel($collection);
    }

    protected function get_elements(array $declarer, string $key): array
    {
        if (isset($declarer[self::ELEMENTS])) return $declarer[self::ELEMENTS];

        if (!isset($declarer[$key]) || !is_array($declarer[$key])) return [];
        return array_filter(array_map(fn(array $element) => $element[Key::NAME] ?? false, $declarer[$key]));
    }

    protected function after_invoke(): void
    {
        if (!$this->database) return;
        $sqls = $this->database->getSqls();
        foreach ($sqls as $sql) $this->recorder->Log($sql);
    }
}